using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using Microsoft.ApplicationBlocks.Updater;

namespace ManualInproc
{
	/// <summary>
	/// Summary description for ManualInprocForm.
	/// </summary>
	public class ManualInprocForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Button updateButton;
		private System.Windows.Forms.Button exitButton;
		private System.Windows.Forms.ListBox eventList;

		public delegate void ActivateCallHandler();
		private ArrayList manifestsToBeActivated = new ArrayList();
		private int applicableManifests = 0;
		private ApplicationUpdaterManager updater = null;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public ManualInprocForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			// Get the updater manager
			updater = ApplicationUpdaterManager.GetUpdater();
			
			// Subscribe for various events
			updater.DownloadStarted +=new DownloadStartedEventHandler(updater_DownloadStarted);
			updater.DownloadProgress += new DownloadProgressEventHandler(updater_DownloadProgress);
			updater.DownloadCompleted += new DownloadCompletedEventHandler(updater_DownloadCompleted);
			updater.DownloadError += new DownloadErrorEventHandler(updater_DownloadError);
			updater.ActivationInitializing += new ActivationInitializingEventHandler(updater_ActivationInitializing);
			updater.ActivationStarted += new ActivationStartedEventHandler(updater_ActivationStarted);
			updater.ActivationInitializationAborted += new ActivationInitializationAbortedEventHandler(updater_ActivationInitializationAborted);
			updater.ActivationError += new ActivationErrorEventHandler(updater_ActivationError);
			updater.ActivationCompleted +=new ActivationCompletedEventHandler(updater_ActivationCompleted);

		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.label1 = new System.Windows.Forms.Label();
			this.updateButton = new System.Windows.Forms.Button();
			this.exitButton = new System.Windows.Forms.Button();
			this.eventList = new System.Windows.Forms.ListBox();
			this.SuspendLayout();
			// 
			// label1
			// 
			this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.label1.Location = new System.Drawing.Point(24, 32);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(224, 23);
			this.label1.TabIndex = 0;
			this.label1.Text = "This is the base version 1.0";
			// 
			// updateButton
			// 
			this.updateButton.Location = new System.Drawing.Point(160, 184);
			this.updateButton.Name = "updateButton";
			this.updateButton.TabIndex = 2;
			this.updateButton.Text = "Update";
			this.updateButton.Click += new System.EventHandler(this.updateButton_Click);
			// 
			// exitButton
			// 
			this.exitButton.Location = new System.Drawing.Point(40, 184);
			this.exitButton.Name = "exitButton";
			this.exitButton.TabIndex = 3;
			this.exitButton.Text = "Exit";
			this.exitButton.Click += new System.EventHandler(this.exitButton_Click);
			// 
			// eventList
			// 
			this.eventList.HorizontalScrollbar = true;
			this.eventList.Location = new System.Drawing.Point(24, 64);
			this.eventList.Name = "eventList";
			this.eventList.Size = new System.Drawing.Size(240, 95);
			this.eventList.TabIndex = 4;
			// 
			// ManualInprocForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(292, 266);
			this.Controls.Add(this.eventList);
			this.Controls.Add(this.exitButton);
			this.Controls.Add(this.updateButton);
			this.Controls.Add(this.label1);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
			this.MaximizeBox = false;
			this.Name = "ManualInprocForm";
			this.Text = "ManualInprocForm";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new ManualInprocForm());
		}

		private void updateButton_Click(object sender, System.EventArgs e)
		{
			try
			{
				Manifest[] manifests = updater.CheckForUpdates();
				applicableManifests = manifests.Length;
				if ( manifests.Length > 0 )
				{
					// Prompt user if he wants to apply the updates
					if( MessageBox.Show(this,"Update for Manual Inproc Application is available, do you want to apply the update?","Update",MessageBoxButtons.YesNo)== DialogResult.Yes)
					{
						foreach(Manifest m in manifests)
						{
							m.Apply = true;
						}
						
						updateButton.Enabled = false;
						
						// download the updates asychronously.
						updater.BeginDownload(manifests);
					
					}
				}
				else
				{
					MessageBox.Show(this,"There are no updates available for this application.","Update", MessageBoxButtons.OK,MessageBoxIcon.Information);
				}
			}
			catch(Exception ex)
			{
				MessageBox.Show(this,ex.Message,"Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
			}
		}

		private void exitButton_Click(object sender, System.EventArgs e)
		{
			Application.Exit();
		}

		private void updater_DownloadStarted(object sender, DownloadStartedEventArgs e)
		{
			UpdateList("DownloadStarted for manifest: " + e.Manifest.ManifestId);
		}

		private void updater_DownloadProgress(object sender, DownloadProgressEventArgs e)
		{
			UpdateList("DownloadProgress for manifest: "+ e.Manifest.ManifestId +
				"- Files: "+e.FilesTransferred+"/"+e.FilesTotal+
				" - Bytes: "+e.BytesTransferred+"/"+e.BytesTotal);
		}

		private void updater_DownloadCompleted(object sender, ManifestEventArgs e)
		{
			UpdateList("DownloadCompleted for manifest: " + e.Manifest.ManifestId);
			
			manifestsToBeActivated.Add(e.Manifest);
			if( manifestsToBeActivated.Count == this.applicableManifests )
			{
				base.Invoke(new ActivateCallHandler(ActivateCall));
			}
		}

		private void ActivateCall()
		{
			ApplicationUpdaterManager updater = ApplicationUpdaterManager.GetUpdater();
			updater.Activate((Manifest[])manifestsToBeActivated.ToArray(typeof(Manifest)));
			manifestsToBeActivated.Clear();
		}

		private void updater_DownloadError(object sender, ManifestErrorEventArgs e)
		{
			UpdateList("DownloadError for manifest: " + e.Manifest.ManifestId +"\n"+e.Exception.Message);
			updateButton.Enabled = true;
		}

		private void updater_ActivationInitializing(object sender, ManifestEventArgs e)
		{
			UpdateList("ActivationInitializing for manifest: " + e.Manifest.ManifestId);
		}

		private void updater_ActivationStarted(object sender, ManifestEventArgs e)
		{
			UpdateList("ActivationStarted for manifest: " + e.Manifest.ManifestId);
		}

		private void updater_ActivationInitializationAborted(object sender, ManifestEventArgs e)
		{
			UpdateList("ActivationInitializationAborted for manifest: " + e.Manifest.ManifestId);
			MessageBox.Show(this,"The Application needs to restart for applying the updates, please restart the application.",
								"Manual Inproc Updates",MessageBoxButtons.OK,MessageBoxIcon.Information);
		}

		private void updater_ActivationError(object sender, ManifestErrorEventArgs e)
		{
			UpdateList("ActivationError for manifest: " + e.Manifest.ManifestId +"\n"+e.Exception.Message);
			updateButton.Enabled = true;
		}

		private void updater_ActivationCompleted(object sender, ActivationCompleteEventArgs e)
		{
			UpdateList("ActivationCompleted for manifest: " + e.Manifest.ManifestId);
		}

        private delegate void UpdateListDelegate(string displayString);

        private void UpdateList(string displayString)
		{
			if (InvokeRequired)
                BeginInvoke(new UpdateListDelegate(InnerUpdateList), displayString);
			else
                InnerUpdateList(displayString);
            
		}

        private void InnerUpdateList(string displayString)
        {
            eventList.Items.Add(displayString);
            eventList.Update();
        }
	}
}
